#include "buffer.h"
#include <string.h>
#include <assert.h>

Buffer :: Buffer(const int len)
{
	assert( len > 0 );
	m_iLen = len;
	m_iOffset = 0;
	m_iLimit = 0;

	m_psBuf = new char[m_iLen];
	assert( m_psBuf != NULL );
}

Buffer :: Buffer( const Buffer & buf )
{
	this->m_iLen = buf.m_iLen;
	this->m_iLimit = buf.m_iLimit;
	this->m_iOffset = buf.m_iOffset;

	this->m_psBuf = new char [ buf. m_iLen ];
	assert( this->m_psBuf != NULL );
	memcpy( this->m_psBuf, buf.m_psBuf, buf.m_iLimit );
}

Buffer :: ~Buffer()
{
	if ( m_psBuf != NULL )
	{
		delete []m_psBuf;
		m_psBuf = NULL;
	}
}

Buffer & Buffer :: operator =( const Buffer & buf )
{
	this->m_iLen = buf.m_iLen;
	this->m_iLimit = buf.m_iLimit;
	this->m_iOffset = buf.m_iOffset;
	assert( this->m_psBuf != NULL );
	memcpy( this->m_psBuf, buf.m_psBuf, buf.m_iLimit );
	return *this;
}

int Buffer :: GetByPos(int index)
{
	int ret = GETC_ERROR;
	if ( index >= 0 && index < m_iLimit )
	{
		ret = m_psBuf[index];
	}
	return ret;
}

int Buffer :: GetByteBufferCopy(char * psOut, int &iLen)
{
	int ret = -1;
	if ( m_iLimit > 0 )
	{
		char * temp = new char[m_iLimit];
		if ( NULL != temp )
		{
			memcpy( temp, m_psBuf, m_iLimit );
			psOut = temp;
			iLen = m_iLimit;
			ret = 0;
		}
	}
	return ret;
}	

char * Buffer :: GetByteBuffer()
{
	return m_psBuf;
}


char * Buffer :: GetRemainByteBuffer()
{
	return m_psBuf+m_iOffset;
}

int Buffer :: GetRemainLen()
{
	return m_iLimit - m_iOffset;
}

int Buffer :: Clear()
{
	m_iLimit = 0;
	m_iOffset = 0;
	return 0;
}

int Buffer :: Append( char c ) 
{
	int ret = -1;
	if ( 0 == InsureSize(1) )
	{
		if ( m_iOffset <= m_iLen-1 )
		{
			m_psBuf[ m_iLimit++ ] = c;
			ret = 0;
		}
	}
	return ret;
}

int Buffer :: Append( const char * psSrc, const int iLen)
{
	int ret = -1;
	if ( iLen > 0 && psSrc != NULL )
	{
		if ( 0 == InsureSize(iLen) )
		{
			memcpy( m_psBuf+m_iLimit, psSrc, iLen );
			m_iLimit += iLen;
			ret = 0;
		}

	}
	return ret;
}

int Buffer :: SetOffset(int index)
{
	int ret = -1;
	if ( index >= 0 && index <= m_iLimit )
	{
		m_iOffset = index; 
		ret = 0;
	}
	return ret;
}

int Buffer :: GetOffset()
{
	return m_iOffset;
}

int Buffer :: InsureSize(int iIncLen)
{
	int ret = 0, iSize = m_iLen;
	
	if ( m_iLimit + iIncLen > iSize )
	{
		while ( m_iLimit+iIncLen > iSize )
		{
			iSize = iSize * 2; 
		}

		char * temp = new char[iSize];

		if ( NULL != temp )
		{
			memcpy( temp, m_psBuf, m_iLimit );
			delete []m_psBuf;
			m_psBuf = temp;
			m_iLen = iSize;
		}
		else
		{
			ret = -1;
		}
	}
	return ret;
}

int Buffer :: SetLimit( int iLimit )
{
	m_iLimit = iLimit;
	return 0;
}

int Buffer :: GetLimit()
{
	return m_iLimit;
}

int Buffer :: GetCapability()
{
	return m_iLen;
}
